import type { AxiosRequestConfig, AxiosResponse, AxiosError, InternalAxiosRequestConfig } from 'axios'

/**
 * @description: request method
 */
export enum RequestEnum {
	GET = 'GET',
	POST = 'POST',
	PUT = 'PUT',
	DELETE = 'DELETE',
}

/**
 * @description 自定义额外请求属性
 * @type loading?: 全局loading			默认	false	不显示loading
 * @type cancel?: 取消上一个重复请求	默认	false	不取消
 * @type encryptable?: 参数是否加密		默认	false 不加密
 * @type sortable?: 请求拦截器的顺序	默认	false 先添加的拦截器最后执行
 * @type showCatchErrorMessage?: 请求拦截器的顺序	默认	true 是否弹出错误信息提示
 * @type isReturnNativeResponse?: 请求响应是否返回原始 response
 */
export interface ExtraRequestConfigBase {
	loading?: boolean
	cancel?: boolean
	encryptable?: boolean
	sortable?: boolean
	isReturnNativeResponse?: boolean
	showCatchErrorMessage?: boolean
}

export interface RequestBaseConfig<T = any> extends Required<ExtraRequestConfigBase> {
	baseURL: string
	url: string
	method: string
	data?: T
	params?: any
}

/**
 * @description 拦截器
 * @type requestInterceptors?: 请求拦截器
 * @type requestInterceptorsCatch?: 请求错误拦截器
 * @type responseInterceptors?: 响应拦截
 * @type responseInterceptorsCatch?: 响应错误拦截器
 */
export interface CustomInterceptors<T = any, D = any> {
	// 请求拦截
	requestInterceptors?: (config: CustomAxiosRequestConfig<T>) => CustomAxiosRequestConfig<T>
	requestInterceptorsCatch?: (err: AxiosError) => any
	// 响应拦截
	responseInterceptors?: (response: AxiosResponse<D, T>) => Promise<AxiosResponse<D, T>>
	responseInterceptorsCatch?: (err: AxiosError) => any
}

/**
 * @description 继承并扩展 类型 AxiosRequestConfig
 * @type interceptors?:	拦截器
 * @type beforeRequest?:	请求发起前处理
 * @type afterResponseThen?: 请求响应后处理
 * @type afterResponseCatch?:	请求响应错误处理
 * @type afterResponseFinally?:	请求响应错误处理
 * @type loading?:	请求全局
 * @type cancel?:	请求取消
 * @type encryptable?:	请求加密
 * @type sortable?:	拦截器执行顺序
 */
export interface RequestHooksConfig<T = any, D = any> {
	interceptors?: CustomInterceptors<T, D>
	beforeRequest?: (config: Required<RequestBaseConfig<T>>) => Required<RequestBaseConfig<T>>
	beforeRequestCatch?: (error: any) => any
	afterResponseThen?: (
		response: AxiosResponse<D, T>,
		baseConfig: Required<RequestBaseConfig<T>>
	) => Promise<IResult<D> | AxiosResponse<D, T>> | IResult<D> | AxiosResponse<D, T>
	afterResponseCatch?: (err: Error | AxiosError<IResult<D>, T>) => any
	afterResponseFinally?: () => any
}

export type CustomAxiosRequestConfig<T = any> = RequestBaseConfig<T> & InternalAxiosRequestConfig<T>

export type RequestConfig<T = any, D = any> = AxiosRequestConfig<T> & ExtraRequestConfigBase & RequestHooksConfig<T, D>

export type RequestOptions<T = any, D = any> = Partial<Exclude<RequestBaseConfig, 'data' | 'params'> & RequestHooksConfig<T, D>>

/**
 * 自定义拦截器管理器的接口定义
 */
export interface CustomInterceptorManager {
	/**
	 * 使用拦截器
	 */
	use: () => {
		requestInterceptorId: number
		responseInterceptorId: number
	}

	/**
	 * 移除拦截器
	 * @param requestInterceptorId 请求拦截器的ID
	 * @param responseInterceptorId 响应拦截器的ID
	 */
	eject: (requestInterceptorId: number, responseInterceptorId: number) => void
}

/**
 * 拦截器映射的类型定义
 */
export type InterceptorsManagerMap = Map<
	string,
	{
		requestInterceptorId: number
		responseInterceptorId: number
		customInterceptorsManager: CustomInterceptorManager
	} | null
>

/**
 * @description 存放取消方法的集合
 */
export interface CancelRequestSource {
	[index: string]: () => void
}

/**
 * @interface RequestEncryptionData<T = string>
 * @description 加密后的请求参数
 */
export interface RequestEncryptionData<T = string> {
	sign: string
	data: T
	timestamp: number
}

/**
 * @description 全局接口响应数据 interface
 * @interface ResponseDecryptionData 响应数据类型
 * @interface R 响应数据类型
 */
export interface ResponseDecryptionData<R> {
	code: string | number
	msg: string
	sign: string
	data: R
	timestamp: number
	channel: number
	decrypt: number
}

/**
 * @description 请求数据 interface
 * @interface IResult 响应数据类型固定参数
 * @interface T 请求具体参数类型-会处理成字符串
 */
export type IRequest<T> = RequestEncryptionData<T>
/**
 * @description 响应数据 interface
 * @type IResult 响应数据类型固定参数
 * @type T 期待获取返回的数据类型
 */
export type IResult<T = any> = Pick<ResponseDecryptionData<T>, 'code' | 'msg' | 'data'>

/**
 * @description 导出响应数据
 */
export interface exportResult {
	data: string
	fileName: string
	code: number
	error?: string
}
export interface exportFileResult {
	data: Blob
}
